/******************************************************************************
**
** INTEL CONFIDENTIAL
** Copyright 2003-2005 Intel Corporation All Rights Reserved.
**
** The source code contained or described herein and all documents
** related to the source code (Material) are owned by Intel Corporation
** or its suppliers or licensors.  Title to the Material remains with
** Intel Corporation or its suppliers and licensors. The Material contains
** trade secrets and proprietary and confidential information of Intel
** or its suppliers and licensors. The Material is protected by worldwide
** copyright and trade secret laws and treaty provisions. No part of the
** Material may be used, copied, reproduced, modified, published, uploaded,
** posted, transmitted, distributed, or disclosed in any way without Intel's
** prior express written permission.
**
** No license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise. Any license under such intellectual property rights
** must be express and approved by Intel in writing.
**
**  FILENAME: micco.cpp
**
**  PURPOSE:  MICCO Driver
**
******************************************************************************/

#include <windows.h>
#include <ceddk.h>
#include <ddkreg.h>
#include <bsp_cfg.h>
#include "micco.h"
#include "monahans.h"
#include "xllp_defs.h"
#include "xllp_i2c.h"
#include "xllp_pm_micco.h"
#include "monahans_base_regs.h"
#include <nkintr.h>
#include <cmthread.h>
#include <CRegEdit.h>
#include <CRefCon.h>
//#include "xllp_mfp_proc_A0.h" //shachar 
#include "xllp_gpio_plat.h"

#ifdef DEBUG
#define ZONE_ERROR (1<<0)
#define ZONE_INIT  (1<<2)
#endif

// SPECIFIC FOR LITTLETON
//
//

#define XLLP_MFP_PMIC_INT_OFFSET    
#define I2C_MUTEX_NAME		TEXT("I2C_CONTROL") 


class PIC:public CMiniThread
{
protected:
    HANDLE m_I2CMutex;
    HANDLE m_MfpRMDHandle;
    HANDLE m_hISTEvent;
    volatile P_XLLP_MFP_RM_DB_ID_T m_pMfpRMDb;
    DWORD m_dwSysIntr;

    volatile int *  m_MFPBase;
    volatile int *  m_I2CBase;
    volatile int *  m_OSTBase;
    volatile int *    m_GPIOBase;
    DWORD m_miccoIrqID;
    HANDLE m_Events[PIC_EVENT_MAX];

public:
    PIC();
    ~PIC();
    DWORD Init();
    BOOL IOControl(  DWORD hOpenContext,  DWORD dwCode,  PBYTE pBufIn,  DWORD dwLenIn,  PBYTE pBufOut,  DWORD dwLenOut,  PDWORD pdwActualOut );
    BOOL PowerUp();

protected:
    void Lock()
    {
        WaitForSingleObject(m_I2CMutex, INFINITE);
    }
    void UnLock()
    {
        ReleaseMutex(m_I2CMutex);
    }
    XLLP_STATUS_T PIC::ReadChipReg(XLLP_UINT8_T reg, XLLP_UINT8_T *value);
    XLLP_STATUS_T PIC::WriteChipReg(XLLP_UINT8_T reg, XLLP_UINT8_T value);

    BOOL MapReg();
    BOOL InitMFPRM();

    DWORD ThreadRun();
};
PIC::PIC():CMiniThread (0, TRUE)
{
    m_MFPBase=NULL;
    m_I2CBase=NULL;
    m_OSTBase=NULL;
    m_GPIOBase=NULL;

    m_I2CMutex=0;
    m_MfpRMDHandle=0;
    m_pMfpRMDb=NULL;

    for(int i=0;i<PIC_EVENT_MAX;i++)
        m_Events[i]=0;
}
XLLP_STATUS_T PIC::ReadChipReg(XLLP_UINT8_T reg, XLLP_UINT8_T *value)
{
    XLLP_STATUS_T ret;
    Lock();
    ret = XllpPmMiccoRead((P_XLLP_I2C_T)m_I2CBase, (P_XLLP_OST_T)m_OSTBase, reg,  value);
    if(ret)
    {
        DEBUGMSG(ZONE_ERROR, (_T("Micco I2C Read Error\r\n")));
    }

//    RETAILMSG(1, (_T("Micco I2C Read :reg[%02x]=%02x\r\n"), reg, *value));
    
    UnLock();
    return ret;
}
XLLP_STATUS_T PIC::WriteChipReg(XLLP_UINT8_T reg, XLLP_UINT8_T value)
{   
    XLLP_STATUS_T ret;
    Lock();
    ret = XllpPmMiccoWrite((P_XLLP_I2C_T)m_I2CBase, (P_XLLP_OST_T)m_OSTBase, reg,  value);
    if(ret)
    {
        DEBUGMSG(ZONE_ERROR,(_T("Micco I2C Write Error\r\n")));
    }

    //RETAILMSG(1, (_T("Micco I2C Write:reg[%02x]=%02x\r\n"), reg, value));
    UnLock();
    return ret;
}



BOOL PIC::MapReg(void)
{   
    if ( m_MFPBase == NULL ) 
    {
        PHYSICAL_ADDRESS ioPhysicalBase = {MONAHANS_BASE_REG_PA_MFP, 0 };
        m_MFPBase = (volatile int *)MmMapIoSpace(ioPhysicalBase, 0x800,FALSE); 

        if ( m_MFPBase==NULL )
        {
            RETAILMSG(1, (_T("MAP MFP Register error ")));
            return FALSE;            
        }
    }

    DEBUGMSG(ZONE_INIT, (_T("Map Read MFP Register 0x%x\r\n"),m_MFPBase));

    if ( m_I2CBase == NULL ) 
    {
        PHYSICAL_ADDRESS ioPhysicalBase = {MONAHANS_BASE_REG_PA_I2C, 0 };
        m_I2CBase = (volatile int *)MmMapIoSpace(ioPhysicalBase, 0x100,FALSE); 

        if ( m_I2CBase==NULL )
        {
            RETAILMSG(1, (_T("MAP I2CBase Register error \r\n")));
            return FALSE;            
        }
    }
        
    DEBUGMSG(ZONE_INIT, (_T("Map Read I2C Register0x%x\r\n"),m_I2CBase ));
        
    if ( m_OSTBase == NULL ) 
    {
        PHYSICAL_ADDRESS ioPhysicalBase = {MONAHANS_BASE_REG_PA_OST, 0 };
        m_OSTBase = (volatile int *)MmMapIoSpace(ioPhysicalBase, 0xF0,FALSE); 

        if ( m_OSTBase==NULL )
        {
            RETAILMSG(1, (_T("MAP m_OSTBase Register error \r\n")));
            return FALSE;            
        }
    }

    DEBUGMSG(ZONE_INIT, (_T("Map Read OST Register0x%x\r\n"),m_OSTBase ));
    
    if (m_GPIOBase == NULL) {

        PHYSICAL_ADDRESS ioPhysicalBase = {MONAHANS_BASE_REG_PA_GPIO, 0 };
        m_GPIOBase= (volatile int *)MmMapIoSpace(ioPhysicalBase, 0xF0,FALSE); 

        if ( m_GPIOBase==NULL )
        {
            RETAILMSG(1, (_T("MAP m_GPIOBase Register error \r\n")));
            return FALSE;            
        }
        

    }

    return TRUE;


}

BOOL PIC::InitMFPRM()
{
    static BOOL bFirstInit=FALSE;

    m_MfpRMDHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
            0, XLLP_MFP_RM_DB_SIZE, MFPRMDB_SHARED_FILENAME );

    if(m_MfpRMDHandle == NULL )
    {
        NKDbgPrintfW(TEXT("[UART] Fail to CreateFileMapping(MFPRMDB_SHARED_FILENAME)! \r\n"));;
        return FALSE;
    }

    if (ERROR_ALREADY_EXISTS != GetLastError()) 
    {
            // The first initialization of this memory-mapped file.
            DEBUGMSG(ZONE_INIT, (TEXT("[UART] First call of CreateFileMapping(MFPRMDB_SHARED_FILENAME)! \r\n")));       

            bFirstInit = TRUE;      

    }else 
    {
            // Memory-mapped file already existed.
            DEBUGMSG(ZONE_INIT, (TEXT("PIC Sequent call of CreateFileMapping(MFPRMDB_SHARED_FILENAME)! \r\n")));

            bFirstInit = FALSE;
    }

    m_pMfpRMDb = (P_XLLP_MFP_RM_DB_ID_T) MapViewOfFile(m_MfpRMDHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
        
    if (NULL == m_pMfpRMDb )
    {
          NKDbgPrintfW(TEXT("[UART] Fail to MapViewOfFile()!\r\n"));
          return FALSE; //if failed
    }

    if (TRUE == bFirstInit) 
    {
            // Need to Initialize RM    
        if (XLLP_STATUS_SUCCESS != XllpMfpResourceManagerInit(m_pMfpRMDb)) 
        {
            NKDbgPrintfW(TEXT("[UART] Fail to XllpMfpResourceManagerInit()!\r\n"));
            return FALSE; //if failed
        }
    }
        
    return TRUE;
}
BOOL PIC::IOControl(  DWORD hOpenContext,  DWORD dwCode,  PBYTE pBufIn,  DWORD dwLenIn,  PBYTE pBufOut,  DWORD dwLenOut,  PDWORD pdwActualOut )
{
    BOOL ret=FALSE;
    switch(dwCode)
    {
        case PIC_IO_INT_DONE:
            //RETAILMSG(1, (_T("[MICCO] PIC_IO_INT_DONE, int %d  \r\n"),m_miccoIrqID));
            InterruptDone( m_dwSysIntr);
            ret=TRUE;
            break;
        case PIC_IO_ENABLE_EVENT:
            if(dwLenIn==sizeof(DWORD))
            {   
                DWORD event=*(DWORD*)pBufIn;
                if(event<0||event>PIC_EVENT_MAX)
                    break;

                XLLP_UINT8_T reg;
                reg=(XLLP_UINT8_T)(XLLP_MICCO_IRQ_MASK_A+(event>>3));
                
                XLLP_UINT8_T value;
                if(ReadChipReg(reg, &value))
                    ret=FALSE;
                value &= ~( 1<<(event&0x7) );
                if(WriteChipReg(reg,value))
                    ret=FALSE;
                
                DEBUGMSG(ZONE_INIT, (_T("Enable Event %d\r\n"),event));
                ret=TRUE;
            }
            break;
        case PIC_IO_DISABLE_EVENT:
            if(dwLenIn==sizeof(DWORD))
            {   
                DWORD event=*(DWORD*)pBufIn;
                if(event<0||event>PIC_EVENT_MAX)
                    break;

                XLLP_UINT8_T reg;
                reg=(XLLP_UINT8_T)(XLLP_MICCO_IRQ_MASK_A+(event>>3));
                
                XLLP_UINT8_T value;
                if(ReadChipReg(reg, &value))
                    ret=FALSE;
                value |= ( 1<<(event&0x7) );
                if(WriteChipReg(reg,value))
                    ret=FALSE;
                
                DEBUGMSG(ZONE_INIT, (_T("Disable Event %d\r\n"),event));
                ret=TRUE;
            }
            ret=TRUE;
            break;
        case PIC_IO_GET_EVENT_HANDLE:

            if(dwLenIn==sizeof(DWORD))
            {   
                DWORD event=*(DWORD*)pBufIn;
                if(event<0||event>PIC_EVENT_MAX)
                    break;

                // Added MSG
                //RETAILMSG(1, (_T("GET EVEN HANDLE Event %d\r\n"),event));
                if(dwLenOut==sizeof(DWORD))
                {
                    *(HANDLE *)pBufOut=m_Events[event];
                }
            }
            ret=TRUE;
            break;
        case PIC_IO_LOCK:
            Lock();
            ret=TRUE;
            break;
        case PIC_IO_UNLOCK:
            UnLock();
            ret=TRUE;
            break;
        case PIC_IO_GET_ONKEY_STATUS:
            if(dwLenOut==sizeof(BOOL))
            {
                XLLP_UINT8_T value;
                if(ReadChipReg(XLLP_MICCO_STATUS_A,&value))
                {   
                    ret=FALSE;
                    break;
                }
                //NKDbgPrintfW(_T("Get Chip Register:0x%x \r\n"),value);
                //when pressed value is 0x04
                *(BOOL *)pBufOut=value&0x1?FALSE:TRUE;

            }
            ret=TRUE;
            break;

        case PIC_IO_GET_USB_CABLE:
            if(dwLenOut==sizeof(BOOL))
            {
                XLLP_UINT8_T value;
                if(ReadChipReg(XLLP_MICCO_STATUS_B,&value))
                {   
                    ret=FALSE;
                    break;
                }
                #ifndef MICCO_B0
                    *(BOOL *)pBufOut=value&0x20?TRUE:FALSE; // must match PIC_EVENT_USB_CABLE_DET event type
                #else
                    *(BOOL *)pBufOut=value&0x1?TRUE:FALSE; // must match PIC_EVENT_USB_CABLE_DET event type
                #endif
                       }
                        break;


        case PIC_IO_GET_PEN_DOWN:
            {
            XLLP_UINT8_T value;
                if(ReadChipReg(XLLP_MICCO_STATUS_A,&value))
                {   
                    ret=FALSE;
                    break;
                }

                //RETAILMSG(1, (_T("Get STATUS_A=0x%x\r\n"),value));
                *(BOOL *)pBufOut=value&0x40?TRUE:FALSE; //0-pen touch not detect; 1-pen touch detect 
            }
            ret=TRUE;
            break;
        case PIC_IO_GET_REG:
            //DEBUGMSG(ZONE_INIT, (_T("Get Chip Register:0x%x \r\n"),*pBufIn));
            //RETAILMSG(1, (_T("Get Chip Register:0x%x \r\n"),*pBufIn));
            if( dwLenIn==sizeof(BYTE) && dwLenOut== sizeof(BYTE) )
            {
                if(ReadChipReg((XLLP_UINT8_T)*pBufIn,(XLLP_UINT8_T*)pBufOut))
                    ret=FALSE;
                else
                    ret=TRUE;
            }
            break;
        case PIC_IO_SET_REG:
            //DEBUGMSG(ZONE_INIT, (_T("Set Chip Register:0x%x \r\n"),*pBufIn));
            //RETAILMSG(1, (_T("Set Chip Register:0x%x \r\n"),*pBufIn));
            if( dwLenIn==2*sizeof(BYTE))
            {
                if(WriteChipReg((XLLP_UINT8_T)*pBufIn,(XLLP_UINT8_T)*(pBufIn+1)))
                    ret=FALSE;
                else
                    ret=TRUE;
            }
            break;
        case PIC_IO_INIT_MICCO_PM:
            DEBUGMSG(ZONE_INIT, (_T("[MICCO] Init MICCO_PM\r\n")));
            XllpPmMiccoInit((P_XLLP_I2C_T)m_I2CBase,(P_XLLP_OST_T)m_OSTBase);
            break;
        case PIC_IO_GET_VCC_CORE:
            DEBUGMSG(ZONE_INIT, (_T("[MICCO] Get Vcc Core\r\n")));
            if( dwLenOut== sizeof(XLLP_UINT32_T) )
            {
                if ( XllpPmMiccoGetVccCore((P_XLLP_I2C_T)m_I2CBase,(P_XLLP_OST_T)m_OSTBase,(XLLP_UINT32_T*)pBufOut)==XLLP_STATUS_SUCCESS) 
                {
                    DEBUGMSG(ZONE_INIT, (_T("[MICCO] Get Vcc Core OK\r\n")));
                    ret = TRUE;
                }
            }
            DEBUGMSG(ZONE_INIT, (_T("[MICCO] Get Vcc Core FAILED\r\n")));
            break;
        
        case PIC_IO_GET_VCC_SRAM:
            DEBUGMSG(ZONE_INIT, (_T("[MICCO] Get Vcc Core\r\n")));
            if( dwLenOut== sizeof(XLLP_UINT32_T) )
            {
                if ( XllpPmMiccoGetVccSram((P_XLLP_I2C_T)m_I2CBase,(P_XLLP_OST_T)m_OSTBase,(XLLP_UINT32_T*)pBufOut)==XLLP_STATUS_SUCCESS) 
                {
                    DEBUGMSG(ZONE_INIT, (_T("[MICCO] Get Vcc Sram OK\r\n")));
                    ret = TRUE;
                }
            }
            DEBUGMSG(ZONE_INIT, (_T("[MICCO] Get Vcc Sram FAILED\r\n")));
            break;

        case PIC_IO_SET_VCC_CORE:
            DEBUGMSG(ZONE_INIT, (_T("[MICCO] Set Vcc Core:0x%x \r\n"),*pBufIn));
            ret=FALSE;
            if ( dwLenIn==sizeof(XLLP_UINT32_T)) 
            {
                XLLP_UINT32_T vcc_core  = *((XLLP_UINT32_T*)pBufIn);
                //change vcc core
                if ( XllpPmMiccoSetVccCore((P_XLLP_I2C_T)m_I2CBase,(P_XLLP_OST_T)m_OSTBase,vcc_core)==XLLP_STATUS_SUCCESS) 
                {
                    ret=TRUE;
                    DEBUGMSG(ZONE_INIT, (_T("[MICCO] Vcc Core Changed!!\r\n")));
                }
            }
            else
                DEBUGMSG(ZONE_INIT, (_T("[MICCO] Set Vcc Core Failed\r\n")));
            break;
        case PIC_IO_SET_VCC_SRAM:
            DEBUGMSG(ZONE_INIT, (_T("Set Vcc SRAM:0x%x \r\n"),*pBufIn));
            
            ret=FALSE;
            if ( dwLenIn==sizeof(XLLP_UINT32_T)) 
            {
                XLLP_UINT32_T vcc_sram  = *((XLLP_UINT32_T*)pBufIn);
                RETAILMSG(1, (_T("[MICCO} Set Vcc SRAM:%d \r\n"),vcc_sram));
                //change vcc sram
                if ( XllpPmMiccoSetVccSram((P_XLLP_I2C_T)m_I2CBase,(P_XLLP_OST_T)m_OSTBase,1400)==XLLP_STATUS_SUCCESS) 
                {
                    ret=TRUE;
                    DEBUGMSG(ZONE_INIT, (_T("Vcc Sram Changed!!\r\n")));
                }
            }
            else
                DEBUGMSG(ZONE_INIT, (_T("Set Vcc Sram Failed\r\n")));
            break;

    }
    return ret;
}

DWORD PIC::Init()
{
    DEBUGMSG(ZONE_INIT, (_T("MICCO Init\r\n")));
    m_I2CMutex=CreateMutex(NULL, FALSE, I2C_MUTEX_NAME);
    if( m_I2CMutex == NULL)
    {
        RETAILMSG(1, (_T("CreateMutex ERROR\r\n")));
        return ERROR_INVALID_DATA;
    }
    if(! InitMFPRM() )
    {
        RETAILMSG(1, (_T("Init MFP Resoruce Manage ERROR\r\n")));
        return ERROR_INVALID_DATA;
    }
    if( !MapReg())
    {
        RETAILMSG(1, (_T("Map Register ERROR\r\n")));
        return ERROR_INVALID_DATA;
    }
   
  
    XllpI2cInit((P_XLLP_I2C_T)m_I2CBase, (P_XLLP_VUINT32_T)m_MFPBase, m_pMfpRMDb, 0);

    //Littleton debug 
       //FOR LITTLETON, GPIO 18: Alt Function 0; Set Interrupt GPIO ( 18 ) 
    XllpMfpSetAfDs ((P_XLLP_VUINT32_T)m_MFPBase,XLLP_MFP_PIN_GPIO18_OFFSET, XLLP_MFP_ALT_FN_0, XLLP_MFP_DS_04X);
    XllpMfpConfigurePullUpDown((P_XLLP_VUINT32_T) m_MFPBase, XLLP_MFP_PIN_GPIO18_OFFSET, XLLP_MFP_PULL_UP);
    XllpGpioSetDirection((P_XLLP_GPIO_T) m_GPIOBase, 18, XLLP_GPIO_DIRECTION_IN);
    XllpGpioSetFallingEdgeDetectEnable((P_XLLP_GPIO_T) m_GPIOBase, 18,  XLLP_ON);

    XLLP_UINT8_T Id;
    if ( ReadChipReg(0,&Id) ) 
        RETAILMSG(1, (_T("MICCO ReadChipReg Failed ( ID ) ...\r\n")));
    else
        RETAILMSG(1, (_T("Micco ID is 0x%x\r\n"),Id));


    //To enable Micco interrupt, must read Event A B C register firstl

    if ( ReadChipReg(XLLP_MICCO_EVENT_A, &Id) ||
        ReadChipReg(XLLP_MICCO_EVENT_B, &Id) ||
        ReadChipReg(XLLP_MICCO_EVENT_C, &Id) ||
        ReadChipReg(XLLP_MICCO_EVENT_D, &Id) ) 
        RETAILMSG(1, (_T("MICCO ReadChipReg interrupt enable Failed ...\r\n")));

    //Mask All Event;

    if (    WriteChipReg(XLLP_MICCO_IRQ_MASK_A,0xFF) || 
            WriteChipReg(XLLP_MICCO_IRQ_MASK_B,0xFF) ||
            WriteChipReg(XLLP_MICCO_IRQ_MASK_C,0xFF)  ||
            WriteChipReg(XLLP_MICCO_IRQ_MASK_D,0xFF))
            RETAILMSG(1, (_T("MICCO ReadChipReg interrupt Mask Failed ...\r\n")));


    m_hISTEvent = CreateEvent(0, FALSE, FALSE, NULL);
    if (m_hISTEvent == NULL) 
    {
        DWORD ret = GetLastError();
        RETAILMSG(1, (_T("%s Error creating Power IC(Micco) interrupt event. Error = %d\r\n"),  "PIC", ret));
        return ERROR_INVALID_DATA;
    }

    // GPIO18, PMIC_INT_N
    m_miccoIrqID=IRQ_GPIO_SHARE(18);
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_miccoIrqID, sizeof(DWORD), &(m_dwSysIntr), sizeof(DWORD), NULL))
    {
        // invalid SDIO SYSINTR value!
        DEBUGMSG(ZONE_ERROR, (TEXT("Error obtaining PowerIC SYSINTR value!\n")));
        m_dwSysIntr = SYSINTR_UNDEFINED;
        return ERROR_INVALID_DATA;
    }

    DEBUGMSG(1, (_T("MICCO Calling InterruptInitialize...m_miccoIrqID = %d, m_dwSysIntr=%d \r\n"),m_miccoIrqID, m_dwSysIntr));

    
    BOOL bSuccess=InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);
    if (!bSuccess)  DEBUGMSG(1, (_T("InterruptInitialize failed \r\n")));

    for(int i=0;i<PIC_EVENT_MAX;i++)
    {
        m_Events[i]=CreateEvent(0,FALSE,FALSE,NULL);
        if(m_Events[i]==NULL)
        {
            RETAILMSG(1, (_T("PIC Create Event Error\r\n "))); 
            return ERROR_INVALID_DATA;
        }
    }

    ThreadStart();

    return ERROR_SUCCESS;
}

PIC::~PIC()
{
    if( m_I2CMutex )
    {
        CloseHandle(m_I2CMutex);
        m_I2CMutex = NULL;

    }else
    {
        DEBUGMSG(ZONE_ERROR, (_T("Mutex should not NULL\r\n")));
        return ;
    }
}

BOOL PIC::PowerUp()
{
    XllpI2cInit((P_XLLP_I2C_T)m_I2CBase, (P_XLLP_VUINT32_T)m_MFPBase, m_pMfpRMDb, 0);
    return TRUE;
}

DWORD PIC::ThreadRun()
{
    while(1)
    {
        WaitForSingleObject(m_hISTEvent,INFINITE);
        for(int i=0;i<3;i++)
        {
            XLLP_UINT8_T value;
            
            ReadChipReg(i+XLLP_MICCO_EVENT_A, &value);
            for(int j=0;j<8;j++)
            {
                if(value&(1<<j))
                {
                    int event;
                    event=i*8+j;
                    if(event<PIC_EVENT_MAX)
                        SetEvent(m_Events[event]);
                    DEBUGMSG(ZONE_INIT, (_T("Micco Event %d\r\n"),event));
                    //RETAILMSG(1, (_T("Micco Event %d\r\n"),event));
                }
            }
        }

        
    }
    return ERROR_SUCCESS;
}
static PIC *m_pPIC=NULL;

extern "C" 
DWORD PIC_Init(
  LPCTSTR pContext,
  LPCVOID lpvBusContext
)
{
    m_pPIC=new PIC();
    
    if(m_pPIC)
    {
        RETAILMSG(1,(_T("Create PIC Object SUCCESS\r\n")));
        m_pPIC->Init();
    }
    return (DWORD)m_pPIC;;
}
extern "C"
BOOL PIC_PreDeinit(
  DWORD hDeviceContext 
)
{

    return TRUE;
}
extern "C"
BOOL PIC_Deinit(
  DWORD hDeviceContext 
)
{   
    if(m_pPIC)
    {
        delete m_pPIC;
        m_pPIC=NULL;
    }
    return TRUE;
}
extern "C"
DWORD PIC_Open(
  DWORD hDeviceContext,
  DWORD AccessCode,
  DWORD ShareMode 
)
{
    return TRUE;
}
extern "C"
BOOL PIC_PreClose(
  DWORD hOpenContext 
)
{
    return TRUE;
}
extern "C"
BOOL PIC_Close(
  DWORD hOpenContext 
)
{
    return TRUE;
}
extern "C"
void PIC_PowerUp(
  DWORD hDeviceContext 
)
{
    m_pPIC->PowerUp();
    return;
}
extern "C"
void PIC_PowerDown(
  DWORD hDeviceContext 
)
{
    return;
}
extern "C"
DWORD PIC_Read(
  DWORD hOpenContext,
  LPVOID pBuffer,
  DWORD Count 
)
{
    DEBUGMSG(ZONE_ERROR,(_T("Don't support %s\r\n"), __FUNCTION__ ));
    return 0;
}
extern "C"
DWORD PIC_Seek(
  DWORD hOpenContext,
  long Amount,
  WORD Type 
)
{
    DEBUGMSG(ZONE_ERROR,(_T("Don't support %s\r\n"), __FUNCTION__ ));
    return 0;
}
extern "C"
DWORD PIC_Write(
  DWORD hOpenContext,
  LPCVOID pBuffer,
  DWORD Count 
)
{
    DEBUGMSG(ZONE_ERROR,(_T("Don't support %s\r\n"), __FUNCTION__ ));
    return 0;
}

extern "C"
BOOL PIC_IOControl(
  DWORD hOpenContext,
  DWORD dwCode,
  PBYTE pBufIn,
  DWORD dwLenIn,
  PBYTE pBufOut,
  DWORD dwLenOut,
  PDWORD pdwActualOut 
)
{
    if(m_pPIC)
    {
        return m_pPIC->IOControl(hOpenContext,dwCode,pBufIn,dwLenIn,pBufOut,dwLenOut,pdwActualOut);
    }
    return FALSE;
}

extern "C"
BOOL
DllEntry(
    HANDLE hDllHandle,
    DWORD  dwReason, 
    LPVOID lpReserved
    )
{
    if ( dwReason==DLL_PROCESS_ATTACH )
    {
        DEBUGREGISTER((HMODULE)hDllHandle);
    }

    return TRUE;
}

#ifdef DEBUG
extern "C" DBGPARAM dpCurSettings = 
{ 
    _T("MICCO"), 
    { 
      _T("Error"), _T("Warning"), _T("Init"), _T(""), 
      _T(""), _T(""), _T(""), _T(""), 
      _T(""), _T(""), _T(""), _T(""), 
      _T("Function"), _T(""), _T(""), _T("") 
    }, 
    ZONE_ERROR|ZONE_INIT
};
#endif
